function init() {
   const fs = require("fs");

   try {
      //  读取文件
      var data = fs.readFileSync('input.txt', 'utf8'); // 确保使用 'utf8' 编码
      console.log(data.toString());
   } catch (err) {
      console.error('Error reading file:', err);
   }

   console.log("程序执行结束!");

   // 事件循环
   // 引入 events 模块
   var events = require('events');
   // 创建 eventEmitter 对象
   var eventEmitter = new events.EventEmitter();

   // 创建事件处理程序
   var connectHandler = function connected() {
      console.log('连接成功。');

      // 触发 data_received 事件 
      eventEmitter.emit('data_received');
   }

   // 绑定 connection 事件处理程序
   eventEmitter.on('connection', connectHandler);

   // 使用匿名函数绑定 data_received 事件
   eventEmitter.on('data_received', function () {
      console.log('数据接收成功。');
   });

   // 触发 connection 事件 
   eventEmitter.emit('connection');

   console.log("程序执行完毕。");

   var fs2 = require("fs");

   fs2.readFile('input.txt', function (err, data) {
      if (err) {
         console.log(err.stack);
         return;
      }
      console.log(data.toString());
   });
   console.log("程序执行完毕");
}
// init()

function initEvent() {
   /***
 * 24-9-11 study
 * 
 * * */
   // // 1.引入 events 模块
   // var events = require('events');
   // // 2.创建eventEmitter 对象
   // var eventEmitter = new events.EventEmitter();
   // // 3.创建事件处理程序
   // var connectHandler = function connected() {
   //    console.log('链接成功...')
   //    // 触发 data_receive 事件
   //    eventEmitter.emit('data_received')
   // }
   // // 4.绑定 connection 事件处理程序
   // eventEmitter.on('connection', connectHandler);
   // // 5.使用匿名函数绑定 data_received 事件
   // eventEmitter.on('data_received', function () {
   //    console.log('数据接收成功')
   // })

   // // 6.触发 connection 事件
   // eventEmitter.emit('connection')
   // console.log('程序执行完毕')

   // // fs模块
   // let fs = require('fs')
   // fs.readFile('input.txt', function(err, data) {
   //    if(err) {
   //       console.log(err.stack);
   //       return;
   //    }
   //    console.log(data.toString())
   // })
   // console.log('程序执行完毕***2222', 1 + +'123')
   /**
    * Node.js EventEmitter
      Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。
      Node.js 里面的许多对象都会分发事件：
      一个 net.Server 对象会在每次有新连接时触发一个事件，
      一个 fs.readStream 对象会在文件被打开的时候触发一个事件。 
      所有这些产生事件的对象都是 events.EventEmitter 的实例。
    * EventEmitter 类
    */
   //event.js 文件
   // var events = require('events'); 
   // var emitter = new events.EventEmitter(); 
   // emitter.on('someEvent', function(arg1, arg2) { 
   //    console.log('listener1', arg1, arg2); 
   // }); 
   // emitter.on('someEvent', function(arg1, arg2) { 
   //    console.log('listener2', arg1, arg2); 
   // }); 
   // emitter.emit('someEvent', 'arg1 参数', 'arg2 参数'); 
   /**
    * 以例子中，emitter 为事件 someEvent 注册了两个事件监听器，然后触发了 someEvent 事件。
    运行结果中可以看到两个事件监听器回调函数被先后调用。 这就是EventEmitter最简单的用法。
    */
   /**1	addListener(event, listener)
      为指定事件添加一个监听器到监听器数组的尾部。
      2	on(event, listener)
      为指定事件注册一个监听器，接受一个字符串 event 和一个回调函数。
      server.on('connection', function (stream) {
      console.log('someone connected!');
      });
      3	once(event, listener)
      为指定事件注册一个单次监听器，即 监听器最多只会触发一次，触发后立刻解除该监听器。
      server.once('connection', function (stream) {
      console.log('Ah, we have our first user!');
      });
      4	removeListener(event, listener)
      移除指定事件的某个监听器，监听器必须是该事件已经注册过的监听器。

      它接受两个参数，第一个是事件名称，第二个是回调函数名称。

      var callback = function(stream) {
      console.log('someone connected!');
      };
      server.on('connection', callback);
      // ...
      server.removeListener('connection', callback);
      5	removeAllListeners([event])
      移除所有事件的所有监听器， 如果指定事件，则移除指定事件的所有监听器。
      6	setMaxListeners(n)
      默认情况下， EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于改变监听器的默认限制的数量。
      7	listeners(event)
      返回指定事件的监听器数组。
      8	emit(event, [arg1], [arg2], [...])
      按监听器的顺序执行执行每个监听器，如果事件有注册监听返回 true，否则返回 false。

       类方法
       序号	方法 & 描述
       1	listenerCount(emitter, event)
      返回指定事件的监听器数量。
         events.EventEmitter.listenerCount(emitter, eventName) //已废弃，不推荐
         events.emitter.listenerCount(eventName) //推荐
      * 
      * 事件
         序号	事件 & 描述
         1	newListener
         event - 字符串，事件名称

         listener - 处理事件函数

         该事件在添加新监听器时被触发。

         2	removeListener
         event - 字符串，事件名称

         listener - 处理事件函数

         从指定监听器数组中删除一个监听器。需要注意的是，此操作将会改变处于被删监听器之后的那些监听器的索引。
    */

   var events = require('events');
   var eventEmitter = new events.EventEmitter();

   // 监听器 #1
   var listener1 = function listener1() {
      console.log('监听器 listener1 执行。');
   }

   // 监听器 #2
   var listener2 = function listener2() {
      console.log('监听器 listener2 执行。');
   }

   // 绑定 connection 事件，处理函数为 listener1 
   eventEmitter.addListener('connection', listener1);

   // 绑定 connection 事件，处理函数为 listener2
   eventEmitter.on('connection', listener2);

   var eventListeners = eventEmitter.listenerCount('connection');
   console.log(eventListeners + " 个监听器监听连接事件。");

   // 处理 connection 事件 
   eventEmitter.emit('connection');

   // 移除监绑定的 listener1 函数
   eventEmitter.removeListener('connection', listener1);
   console.log("listener1 不再受监听。");

   // 触发连接事件
   eventEmitter.emit('connection');

   eventListeners = eventEmitter.listenerCount('connection');
   console.log(eventListeners + " 个监听器监听连接事件。");

   console.log("程序执行完毕。");
}
// initEvent()

async function errInit() {
   // 引入 EventEmitter
   let events = require('events');
   let emitter = new events.EventEmitter();

   // 使用 Promise 包装 setTimeout
   await new Promise(resolve => {
      setTimeout(() => {
         console.log(1 + 1);
         resolve(); // 定时器完成后调用 resolve
      }, 1000);
   });

   // 触发错误事件
   emitter.emit('error');
}

// 监听错误事件
const events = require('events');
let emitter = new events.EventEmitter();
emitter.on('error', () => {
   console.log('An error occurred!');
});

// errInit();

//缓冲区 --转编码使用的
function initBuffer() {
   //  const buf = Buffer.from('runoob', 'ascii');
   //  // 将每个字节编码为两个十六进制字符。
   //  console.log(buf.toString('hex'))
   //  // Base64 编码。
   //  console.log(buf.toString('base64'))
   //  // 仅支持 7 位 ASCII 数据。如果设置去掉高位的话，这种编码是非常快的。
   //  console.log(buf.toString('utf8'))
   //  // 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
   //  console.log(buf.toString('base64'))
   //  // 2 或 4 个字节，小字节序编码的 Unicode 字符。支持代理对（U+10000 至 U+10FFFF）。
   //  console.log(buf.toString('utf16le'))
   //  //ucs2 - utf16le 的别名。
   //  console.log(buf.toString('ucs2'))
   //  console.log(buf.toString('utf16le'))
   //  // latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
   //  console.log(buf.toString('latin1'))
   // // binary - latin1
   // console.log(buf.toString('binary'))
   // console.log(buf.toString('latin1'))

   // 创建一个长度为 10、且用 0 填充的 Buffer。
   // const buf = Buffer.alloc(100)
   // // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
   // const buf4 = Buffer.from([1, 2, 3]);
   // console.log(buf, '*****')
   // console.log(buf4, '****')
   // // buf.write(string[, offset[, length]][, encoding]) 
   // const len = buf.write('wwww.baidu.com13213213213')
   // console.log("写入字节数 : "+  len);
   // // buf.toString([encoding[, start[, end]]])
   // const buf66 = Buffer.from('runoob', 'ascii');
   // //从缓冲区读取数据
   // console.log( buf66.toString('ascii'), '读取数据');


   // 将 Buffer 转换为 JSON 对象 ----返回JSON 对象 

   const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
   const json = JSON.stringify(buf);

   // 输出: {"type":"Buffer","data":[1,2,3,4,5]}
   console.log(json);

   const copy = JSON.parse(json, (key, value) => {
      return value && value.type === 'Buffer' ?
         Buffer.from(value.data) :
         value;
   });

   // 输出: <Buffer 01 02 03 04 05>
   console.log(copy);

   // Buffer.concat(list[, totalLength])  缓冲区合并
   const buffer11 = Buffer.from('孙悟空')
   const buffer22 = Buffer.from('猪八戒')
   const buffer33 = Buffer.concat([buffer11, buffer22])
   console.log(buffer33.toString(), 'buffer33内容为----')

   //缓冲区比较 buf.compare(otherBuffer);
   var buffer1 = Buffer.from('123456');
   var buffer2 = Buffer.from('456789');
   var result = buffer1.compare(buffer2);

   if (result < 0) {
      console.log(buffer1 + " 在 " + buffer2 + "之前");
   } else if (result == 0) {
      console.log(buffer1 + " 与 " + buffer2 + "相同");
   } else {
      console.log(buffer1 + " 在 " + buffer2 + "之后");
   }

   //拷贝缓冲区 buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])

   var buf1 = Buffer.from('abcd');
   var buf2 = Buffer.from('哮');
   //将 buf2 插入到 buf1 指定位置上
   buf2.copy(buf1, 1);
   console.log(buf1.toString());
   // 缓冲区裁剪 buf.slice([start[, end]])
   var people = Buffer.from('runoob');
   // 剪切缓冲区
   var buffer2 = people.slice(0, 2);
   console.log("buffer2 content: " + buffer2.toString());
}
// initBuffer()

//Node.js Stream(流)
/**
 * Stream 是一个抽象接口，Node 中有很多对象实现了这个接口。例如，对http 服务器发起请求的request 对象就是一个 Stream，还有stdout（标准输出）。

 */
function StreamInit() {
   var fs = require("fs");
   console.log('99999')
   // 写入流
   var data = '***韩立-我是让写入的数据12121212****';

   // 创建一个可以写入的流，写入到文件 output.txt 中
   var writerStream = fs.createWriteStream('input.txt');

   // 使用 utf8 编码写入数据
   writerStream.write(data, 'UTF8');

   // 标记文件末尾
   writerStream.end();

   // 处理流事件 --> finish、error
   writerStream.on('finish', function () {
      console.log("写入完成。");
   });

   writerStream.on('error', function (err) {
      console.log(err.stack);
   });

   console.log("程序执行完毕");
   //从流中读取数据
   //创建可读流
   const readerStream = fs.createReadStream('output.txt');
   // 设置编码为 UTF8
   readerStream.setEncoding('utf-8')
   //处理流事件 ---> data， end， and  error
   readerStream.on('data', function (chunk) {
      data += chunk;
   })
   readerStream.on('end', function () {
      console.log(data, '******363')
   })
   readerStream.on('error', function (err) {
      console.log(err.stack); // 显示错误堆栈
   })
   /**
    *  管道流
    * 管道提供了一个输出流到输入流的机制。
    * 通常我们用于从一个流中获取数据并将数据传递到另外一个流中。
    * pipe()
    *  */
   readerStream.pipe(writerStream)
   /**
    * 链式流--可以使用他来 压缩和解压文件
      链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。
      接下来我们就是用管道和链式来压缩和解压文件。
    */
   let zlib = require('zlib')

   // 压缩 input.txt 文件为 input.txt.gz
   const inputFilePath = 'input.txt'; // 确保这个文件存在
   const outputFilePath = 'input.zip';

   fs.createReadStream(inputFilePath)
      .pipe(zlib.createGzip())
      .pipe(fs.createWriteStream(outputFilePath))
      .on('finish', () => {
         console.log('文件压缩完成。。。');
      })
      .on('error', (err) => {
         console.error('发生错误:', err);
      });

   // 解压 input.zip 文件为 output.txt
   /**
    * 解压报错----
    */
   // fs.createReadStream('input.zip')
   //    .pipe(zlib.createGunzip())
   //    .pipe(fs.createWriteStream(outputFilePath))
   //    .on('finish', () => {
   //       console.log('文件解压完成。。。');
   //    })
   //    .on('error', (err) => {
   //       console.error('发生错误:', err);
   //    });
}
// StreamInit()

/***
 * Node.js模块系统
 */

function moduleInit() {
   let h = require('./hello')
   h.world()
}
// moduleInit()


/***
 * Node.js函数
 */

function funInit() {
   var http = require("http");

   function onRequest(request, response) {
      response.writeHead(200, { "Content-Type": "text/plain" });
      response.write("Hello World");
      response.end();
   }

   http.createServer(onRequest).listen(8888);

}
// funInit()


/**
    * Node.js 路由
   在 Node.js 中，路由（Routing）是指确定如何响应对特定端点（URL 路径）的 HTTP 请求的过程。

   我们要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数，随后路由需要根据这些数据来执行相应的代码。

   因此，我们需要查看 HTTP 请求，从中提取出请求的 URL 以及 GET/POST 参数。
   这一功能应当属于路由还是服务器（甚至作为一个模块自身的功能）确实值得探讨，但这里暂定其为我们的HTTP服务器的功能。

   我们需要的所有数据都会包含在 request 对象中，该对象作为 onRequest() 回调函数的第一个参数传递。
   但是为了解析这些数据，我们需要额外的 Node.JS 模块，它们分别是 url 和 querystring 模块。
            url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
            http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
            querystring.parse(queryString)["foo"]    |
                                            |
            querystring.parse(queryString)["hello"]

 */
// function routingInit() {
//     const http = require('http')
//     const url = require('url')
//     function onRequest(request, response) {
//     // 使用 URL 类解析请求的 URL
//     const url = new URL(request.url, `http://${request.headers.host}`);
//     const pathname = url.pathname;
//       console.log("Request for " + pathname + " received.");
//       response.writeHead(200, {"Content-Type": "text/plain"});
//       response.write("Hello World");
//       response.end();
//     }
//     http.createServer(onRequest).listen(8888);
//     console.log("Server has started.");
// }
// exports.start = routingInit;
// routingInit()
//根据前面的 event 绑定，
//直接将事件名定义成路径还是很不错的，不过要区分 request.method 是 get 还是 post ，可以分两个文件处理

const dataHttp = [
   {
      id: 1,
      name: '孙悟空',
   },
   {
      id: 2,
      name: '猪八戒',
   },
   {
      id: 3,
      name: '二郎神',
   },
]

function httpFun() {
   // 引入必要的模块
   var http = require("http"); // 用于创建 HTTP 服务器
   var url = require('url'); // 用于解析 URL（未使用，但可以用于扩展）
   const { exit } = require("process"); // 用于退出进程（未使用，但可以用于扩展）
   var events = require('events'); // 用于事件处理

   // 创建 eventEmitter 对象
   var eventEmitter = new events.EventEmitter();

   // 定义根路径的处理
   eventEmitter.on('/', function (method, response) {
      response.writeHead(200, {
         'Content-Type': 'application/json; charset=utf-8', // 设置内容类型为 JSON 并指定字符编码
         'Access-Control-Allow-Origin': '*', // 允许所有域名
         'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', // 允许的方法
         'Access-Control-Allow-Headers': 'Content-Type' // 允许的请求头
      }); // 设置响应头
      response.end(JSON.stringify(dataHttp)); // 发送响应内容
   });

   // 定义 404 路径的处理
   eventEmitter.on('404', function (method, url, response) {
      response.writeHead(404,
         {
            'Content-Type': 'application/json; charset=utf-8', // 设置内容类型为 JSON 并指定字符编码
            'Access-Control-Allow-Origin': '*', // 允许所有域名
         }
      ); // 设置响应头
      response.end('404 Not Found\n'); // 发送 404 响应内容
   });
   // 启动 HTTP 服务器
   http.createServer(function (request, response) {
      console.log(request.url); // 打印请求的 URL

      // 处理预检请求（OPTIONS）
      if (request.method === 'OPTIONS') {
         response.writeHead(204, {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
            'Access-Control-Allow-Headers': 'Content-Type'
         });
         response.end();
         return;
      }

      // 分发请求到相应的处理函数
      if (eventEmitter.listenerCount(request.url) > 0) {
         // 如果有对应的事件处理器，触发相应事件
         eventEmitter.emit(request.url, request.method, response);
      } else {
         // 否则触发 404 事件
         eventEmitter.emit('404', request.method, request.url, response);
      }
   }).listen(8888); // 监听 8888 端口
   console.log('Server running at http://127.0.0.1:8888/'); // 输出服务器运行信息

}
// httpFun()


/**
 * Node.js 全局对象
 */

/**
 * Node.js 全局对象
JavaScript 中有一个特殊的对象，称为全局对象（Global Object），它及其所有属性都可以在程序的任何地方访问，即全局变量。

在浏览器 JavaScript 中，通常 window 是全局对象， 而 Node.js 中的全局对象是 global，所有全局变量（除了 global 本身以外）都是 global 对象的属性。

在 Node.js 我们可以直接访问到 global 的属性，而不需要在应用中包含它。
 */




function printHello() {
   // 输出全局变量 __filename 的值
   console.log(__filename, '2232323');
   console.log("Hello, World!");
   console.error('*****')
   /**
    * 	exitCode
       进程退出时的代码，
       如果进程优通过 process.exit() 退出，不需要指定退出码。
    */
   process.on('exit', function (code) {

      // 以下代码永远不会执行
      setTimeout(function () {
         console.log("该代码不会执行");
      }, 0);

      console.log('退出码为:', code);
   });
   console.log("程序执行结束");
   // 输出当前目录
   console.log('当前目录: ' + process.cwd());

   // 输出当前版本
   console.log('当前版本: ' + process.version);

   // 输出内存使用情况
   console.log(process.memoryUsage());

}
// setTimeout(printHello, 2000); 
// setInterval(printHello, 2000);

// Node.js 常用工具
/**
   util.callbackify(original) 将 async 异步函数（或者一个返回值为 Promise 的函数）
   转换成遵循异常优先的回调风格的函数，例如将 (err, value) => ... 回调作为最后一个参数。
    在回调函数中，第一个参数为拒绝的原因（如果 Promise 解决，则为 null），第二个参数则是解决的值。
 */
const util = require('util');
function toolInit() {
   // async function fn() {
   //    return 'hello world';
   // }
   // const callbackFunction = util.callbackify(fn)
   // callbackFunction((err, ret) => {
   //    if (err) throw err;
   //    console.log(ret);
   // });
   // function fn() {
   //    return Promise.reject(null)
   // }
   // // 回调函数是异步执行的，并且有异常堆栈错误追踪。
   // const callbackFunction = util.callbackify(fn)
   // callbackFunction((err, ret) => {
   //    // 当Promise 被以 null 拒绝时，它被包装成为 Error 并且原始值存储在 `reason` 中。
   //    err && err.hasOwnProperty('reason') && err.reason === null;
   // })

   // util.inherits
   // util.inherits(constructor, superConstructor) 是一个实现对象间原型继承的函数。
   
   function Base() {
      this.name = 'base';
      this.base = 999;
      this.sayHello = function(){
         console.log('hello' + this.name)
      }
   }
   Base.prototype.showName = function() {
      console.log(this.name)
   }
   function Sub() {
      this.name = 'sub'
   }
   util.inherits(Sub, Base)
   let objBase = new Base()  
   objBase.showName()
   objBase.sayHello()
   console.log(objBase)
   let objSub = new Sub(); 
   objSub.showName(); 
   console.log(objSub); 

  /**
   * 注意：Sub 仅仅继承了Base 在原型中定义的函数
   * 而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。
    同时，在原型中定义的属性不会被 console.log 作 为对象的属性输出。
    如果我们去掉 objSub.sayHello(); 这行的注释，将会看到：
   */





} toolInit()


























function mySqlInit() {
   // 数据库都没有启动----
   var mysql = require('mysql');
   var connection = mysql.createConnection({
      host: 'localhost',
      user: 'root',
      password: '123456',
      database: 'test'
   });

   connection.connect();

   connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
      if (error) throw error;
      console.log('The solution is: ', results[0].solution);
   });
}
// mySqlInit()
